package org.sepheriel.airy2d.math;



import java.util.ArrayList;
import java.util.List;

import org.sepheriel.airy2d.physic.Rectangle;
import org.sepheriel.airy2d.tiles.Tile;

public class QuadTree {
	
	private Rectangle root;
	private List render;
	QuadTree TL;
	QuadTree TR;
	QuadTree BL;
	QuadTree BR;

	
	
	public QuadTree(Rectangle _root) {
		
		this.root = new Rectangle(_root.getPos(), _root.getHeight(), _root.getWidth());

		this.render = new ArrayList();
		
		if(_root.getHeight()==4096) {

			//System.out.println("This "+this.root.toString());
			//System.out.println("TL: "+getTL(this.root).toString());
			//System.out.println("TR: "+getTR(this.root).toString());
			//System.out.println("BL: "+getBL(this.root).toString());
			//System.out.println("BR: "+getBR(this.root).toString());
		}
		
		
		if(_root.getHeight() <= 256)
		{
			//System.out.println("iam a bottom node"+this.root.toString());
		} else {
			this.TL = new QuadTree(getTL(root));
			this.TR = new QuadTree(getTR(root));
			this.BL = new QuadTree(getBL(root));
			this.BR = new QuadTree(getBR(root));
		}
		
	}
	
	public Rectangle getTL(Rectangle node) {
		Rectangle temp = new Rectangle(node);
		
		temp.setHeight(node.getHeight()/2);
		temp.setWidth(node.getWidth()/2);

		return temp;
	}
	
	public Rectangle getTR(Rectangle node) {
		Rectangle temp = new Rectangle(node);
		
		temp.setHeight(node.getHeight()/2);
		temp.setWidth(node.getWidth()/2);
				
		temp.setX(node.getX() +  node.getWidth()/2);

		return temp;
	}
	
	public Rectangle getBL(Rectangle node) {
		Rectangle temp = new Rectangle(node);
		
		temp.setHeight(node.getHeight()/2);
		temp.setWidth(node.getWidth()/2);
				
		temp.setY(node.getY()+node.getHeight()/2);

		return temp;
	}
	
	public Rectangle getBR(Rectangle node) {
		Rectangle temp = new Rectangle(node);
		
		temp.setHeight(node.getHeight()/2);
		temp.setWidth(node.getWidth()/2);
				
		temp.setX(node.getX() + node.getWidth ()/2);
		temp.setY(node.getY() + node.getHeight()/2);

		return temp;
	}
	
	public void insertTile(Tile _tile) {
		
		if(_tile == null) {
			System.out.println("Fuck");
			return;
		}
		
		if(this.root.getHeight() <= 256) {
			
			render.add(_tile);
			//System.out.println("node: " + root.toString());
			//System.out.println("insert tile: " + _tile.getPos());
			
		}
		else {
			//System.out.println(TL);
			//System.out.println(TR);
			//System.out.println(BL);
			//System.out.println(BR);
			if(this.TL.root.inside(_tile.getMid())) {
				TL.insertTile(_tile);
			} else if (this.TR.root.inside(_tile.getMid())) {
				TR.insertTile(_tile);
			} else if (this.BL.root.inside(_tile.getMid())) {
				BL.insertTile(_tile);
			} else if (this.BR.root.inside(_tile.getMid())) {
				BR.insertTile(_tile);
			} else {
				/*System.out.println(root.toString());
				System.out.println(_tile.getPos().toString());
				System.out.println("Tile doesen't fit");*/
			}
		}
	}
	
	public void findTiles(Rectangle _area, List retTile)
	{
		if(_area.overlap(root)) {
			//System.out.println("Ho");
			
			if(this.root.getHeight() <= 256) {
				
				retTile.addAll(this.render);
				//System.out.println("Adding Tiles: " +render.size());
			} else {
					TL.findTiles(_area, retTile);
					TR.findTiles(_area, retTile);
					BL.findTiles(_area, retTile);
					BR.findTiles(_area, retTile);
			}
		
		}
	}

	public List getRender() {
		return render;
	}

	public void setRender(List render) {
		this.render = render;
	}
	
}
